<?php

namespace payment;

use think\facade\Config;
use think\facade\Db;
use think\facade\Log;
use DateTime;
use DateTimeZone;

class WorldFirstService
{
    private $clientIp;

    public $clientId;
    private $apiUrl;
    private $privateKey;
    private $publicKey;
    private $customerId;
    private $language;
    private $contact_entity_id;

    public $card_bin;

    public function __construct($configName = 'worldfirst')
    {
        date_default_timezone_set('UTC');

        $config = Config::get($configName);

        $this->clientIp = $config['client_ip'] ?? '';
        $this->clientId = $config['client_id'] ?? '';
        $this->apiUrl = $config['api_url'] ?? '';
        $this->customerId = $config['customer_id'] ?? '';
        $this->language = $config['language'] ?? '';
        $this->privateKey = openssl_get_privatekey($config['private_key_content']);
        $this->publicKey = openssl_get_publickey($config['public_key_content']);
        $this->contact_entity_id = $config['contact_entity_id'] ?? '';
        $this->card_bin = ($configName == 'worldfirst') ? 10 : 13;
    }


    /**
     * 申请卡片
     * @param array $params 卡片参数
     * @return array
     */
    public function applyCard($params)
    {
        $uri = '/amsin/api/v1/business/worldcard/applyCard';
        $requestBody = json_encode([
            'requestId' => $params['request_id'] ?? uniqid('card_', true),
            'cardNickName' => $params['card_nickname'] ?? '',
            'contactEntityId' => $params['contact_entity_id'] ?? $this->contact_entity_id,
            'env' => [
                'clientIp' => $params['client_ip'] ?? $this->clientIp,
                'language' => $params['language'] ?? $this->language
            ]
        ]);

        return $this->request($uri, $requestBody);
    }

    /**
     * 查询卡片列表
     * @param array $params 查询参数
     * @return array
     */
    public function getCardList($params = [])
    {
        $uri = '/amsin/api/v1/business/worldcard/queryCardList';
        $requestBody = [
            'pageNumber' => $params['page_number'] ?? 1,
            'pageSize' => $params['page_size'] ?? 10
        ];
        if (isset($params['card_nick_name'])) {
            $requestBody['cardNickName'] = $params['card_nick_name'];
        }
        if (isset($params['card_no_last4'])) {
            $requestBody['cardNoLast4'] = $params['card_no_last4'];
        }

        $requestBody = json_encode($requestBody);
        return $this->request($uri, $requestBody);
    }

    //查询企业联系人列表
    public function queryContactList()
    {
        $uri = '/amsin/api/v1/business/worldcard/queryContactList';
        $requestBody = json_encode([

            'env' => [
                'clientIp' => $this->clientIp,
                'language' => $this->language
            ]
        ]);
        return $this->request($uri, $requestBody);
    }

    /**
     * 查询卡片详情
     * @param string $assetId 卡片ID
     * @return array
     */
    public function getCardDetail($assetId)
    {
        $uri = '/amsin/api/v1/business/worldcard/queryCardDetail';

        $requestBody = json_encode([
            'assetId' => $assetId,
            'env' => [
                'clientIp' => $this->clientIp,
                'language' => $this->language
            ]
        ]);
        return $this->request($uri, $requestBody);
    }

    /**
     * 查询卡片敏感信息
     * @param string $assetId 卡片ID
     * @return array
     */
    public function getCardSensitiveInfo($assetId)
    {
        $uri = '/amsin/api/v1/business/worldcard/queryCardSensitiveInfo';
        $requestBody = json_encode([
            'assetId' => $assetId,
            'env' => [
                'clientIp' => $this->clientIp,
                'language' => $this->language
            ]
        ]);

        return $this->request($uri, $requestBody);
    }

    /**
     * 更新卡片状态
     * @param string $assetId 卡片ID
     * @param string $operateType 操作类型可取值范围：
     *  FREEZE：冻结卡片
     *  UNFREEZE：解冻卡片
     *  CANCEL：删除卡片
     * @return array
     */
    public function updateCardStatus($assetId, $operateType)
    {
        $uri = '/amsin/api/v1/business/worldcard/updateCardStatus';
        $requestBody = json_encode([
            'requestId' => time(),
            'assetId' => $assetId,
            'operateType' => $operateType,
            'env' => [
                'clientIp' => $this->clientIp,
                'language' => $this->language
            ]
        ]);
        return $this->request($uri, $requestBody);
    }

    /**
     * 更新卡片限额
     * @param array $params 限额参数
     * @return array
     */
    public function updateCardLimit($params)
    {
        $uri = '/amsin/api/v1/business/worldcard/updateCardLimit';
        $data = [
            'assetId' => $params['asset_id'],
            'env' => [
                'clientIp' => $params['client_ip'] ?? $this->clientIp,
                'language' => $params['language'] ?? $this->language
            ]
        ];
        if ($params['daily_limit_max'] > 0) {
            $data['dailyLimitMax'] = $params['daily_limit_max'];
        }
        if ($params['monthly_limit_max'] > 0) {
            $data['monthlyLimitMax'] = $params['monthly_limit_max'];
        }
        if ($params['per_transaction_limit_max'] > 0) {
            $data['perTransactionLimitMax'] = $params['per_transaction_limit_max'];
        }
        if ($params['per_card_limit_max'] > 0) {
            $data['perCardLimitMax'] = $params['per_card_limit_max'];
        }
        $requestBody = json_encode($data);
        return $this->request($uri, $requestBody);
    }

    /**
     * 查询交易记录
     * @param array $params 查询参数
     * @return array
     */
    public function getTransactionList($params = [])
    {
        $uri = '/amsin/api/v1/business/worldcard/queryBillList';
        $requestBody = json_encode($params);
        return $this->request($uri, $requestBody);
    }

    public function queryOtpConfig($params = [])
    {
        $uri = '/amsin/api/v1/business/worldcard/queryOtpConfig';
        $params = [
            'requestId' => time(),
            'env' => [
                'clientIp' => $this->clientIp,
                'language' => $this->language
            ]
        ];
        $requestBody = json_encode($params);
        return $this->request($uri, $requestBody);
    }

    public function updateOtpConfig()
    {
        $uri = '/amsin/api/v1/business/worldcard/updateOtpNotifyConfig';
        $data = [
            'requestId' => time(),
            'env' => [
                'clientIp' => $this->clientIp,
                'language' => $this->language,

            ],
            'otpApiNotifyPreference' => 'ON'

        ];
        $requestBody = json_encode($data);
        return $this->request($uri, $requestBody);
    }

    /**
     * 获取签名内容
     * @param string $uri 请求URI
     * @param string $requestBody 请求体
     * @param string $timeString 时间字符串
     * @return string
     */
    private function getSignContents($uri, $requestBody, $timeString)
    {
        return "POST " . $uri . "\n" . $this->clientId . "." . $timeString . "." . $requestBody;
    }

    /**
     * 生成签名
     * @param string $data 待签名数据
     * @return string
     */
    private function sign($data)
    {
        if (!openssl_sign($data, $signature, $this->privateKey, OPENSSL_ALGO_SHA256)) {
            throw new \Exception('签名失败');
        }
        return urlencode(base64_encode($signature));
    }

    /**
     * 发送请求
     * @param string $uri 请求URI
     * @param string $requestBody 请求体
     * @return array
     */
    private function request($uri, $requestBody)
    {

        $dateTime = new DateTime('now', new DateTimeZone(config('app.default_timezone')));
        $timeString = $dateTime->format(DateTime::ATOM);

        $data = $this->getSignContents($uri, $requestBody, $timeString);
        $signature = $this->sign($data);
        $signHeader = "algorithm=RSA256,keyVersion=2,signature=" . $signature;

        $headers = [
            'Content-Type: application/json',
            "Signature: $signHeader",
            'Client-Id: ' . $this->clientId,
            'Request-Time: ' . $timeString,
            'traceid:' . uniqid(),
            'Connected-CustomerId: ' . $this->customerId
        ];
        trace($headers);
        trace($requestBody);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->apiUrl . $uri);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        trace('res:' . $response);
        if ($httpCode != 200) {
            trace($response, 'error');
            throw new \Exception('WorldFirst API请求失败');
        }
        $result = json_decode($response, true);
        $row = [
            'create_time' => date('Y-m-d H:i:s'),
            'request' => $requestBody,
            'response' => $response,
            'resultStatus' => $result['result']['resultStatus'] ?? '',
        ];

        //拿锁失败，进行第二次尝试
        if ($result['result']['resultCode'] == 'SYSTEM_ERROR') {
            $response2 = curl_exec($ch);
            trace('res2:' . $response2);
            $result = json_decode($response2, true);
            $row['response2'] = $response2;
            $row['resultStatus2'] = $result['result']['resultStatus'];
        }
        Db::name('cardApiLog')->insert($row);
        curl_close($ch);
        return $result;
    }
}